home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_183 / mklib / mklib.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  16KB  |  541 lines

  1. /*
  2.     Mklib 1.0 - a source file generator for Amiga shared libraries
  3.     Compiled with Manx v3.6a small code model/16 bit int. (see makefile)
  4.  
  5.     copyright 1988 Edwin Hoogerbeets
  6.  
  7.     This software and the files it produces are freely redistributable
  8.     as long there is no charge beyond reasonable copy fees and as long
  9.     as this notice stays intact.
  10.  
  11.     Thanks to Jimm Mackraz for Elib on Fish 87, from which much of this
  12.     program is lifted. Also thanks to Neil Katin for his mylib.asm upon
  13.     which elib is based.
  14. */
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include <edlib.h>
  18. #include "mklib.h"
  19.  
  20. void error(msg)
  21. char *msg;
  22. {
  23.     fprintf(stderr,"Error: %s\n",msg);
  24.     exit(1);
  25. }
  26.  
  27. void writeto(file,header)
  28. FILE *file;
  29. char *header[];
  30. {
  31.     int index = 0;
  32.  
  33.     while ( header[index] != NULL  )
  34.         fprintf(file,"%s\n",header[index++]);
  35. }
  36.  
  37. /* init opens and initializes all the output files */
  38. void init()
  39. {
  40.     /* open file with startup code */
  41.     if ( (startup = fopen("startup.asm","w")) == NULL )
  42.         error("Could not open startup code file");
  43.  
  44.     /* write the header and the body to the file */
  45.     writeto(startup,asmheader);
  46.     writeto(startup,startupcode);
  47.  
  48.     /* we are finished with the startup code file */
  49.     fclose(startup);
  50.  
  51.     /* open romtag file */
  52.     if ( (romtag = fopen("rtag.asm","w")) == NULL )
  53.         error("Could not open romtag file");
  54.  
  55.     /* write the header and the romtag info */
  56.     writeto(romtag,asmheader);
  57.     writeto(romtag,rtag);
  58.  
  59.     /* we are finished with this one too */
  60.     fclose(romtag);
  61.  
  62.  
  63.     /* open library include file */
  64.     if ( (inc = fopen("lib.h","w")) == NULL )
  65.         error("Could not open library include file");
  66.  
  67.     /* write the header and the info */
  68.     writeto(inc,cheader);
  69.     writeto(inc,incbody);
  70.  
  71.     /* we are finished with this one too */
  72.     fclose(inc);
  73.  
  74.     /* open the interface, link and make file for processing and add in
  75.        the appropriate header info */
  76.  
  77.     /* open library file */
  78.     if ( (lib = fopen("lib.c","w")) == NULL )
  79.         error("Could not open library main file");
  80.  
  81.     /* write the header */
  82.     writeto(lib,cheader);
  83.  
  84.     /* open link header file */
  85.     if ( (linkh = fopen("link.h","w")) == NULL )
  86.         error("Could not open link header main file");
  87.  
  88.     /* write the header */
  89.     writeto(linkh,cheader);
  90.  
  91.     /* open library interface file */
  92.     if ( (interface = fopen("interface.asm","w")) == NULL )
  93.         error("Could not open library interface file");
  94.  
  95.     /* write the header */
  96.     writeto(interface,asmheader);
  97.     writeto(interface,faceheader);
  98.  
  99.     /* open library linker file */
  100.     if ( (link = fopen("link.asm","w")) == NULL )
  101.         error("Could not open library linker file");
  102.  
  103.     /* write the header */
  104.     writeto(link,asmheader);
  105.     writeto(link,linkhead);
  106.  
  107.     /* open makefile */
  108.     if ( (makefile = fopen("makefile","w")) == NULL )
  109.         error("Could not open makefile");
  110.  
  111.     /* write the header */
  112.     writeto(makefile,makeheader);
  113.  
  114.     return();
  115. }
  116.  
  117.  
  118. /* rudimentary scanner for picking up tokens to be parsed for function
  119.    declarations */
  120. int getoken(file)
  121. char *file;
  122. {
  123.     char c;
  124.     short cont = 1, eoc = 0;    /* continue loop and end of comment flags */
  125.  
  126.     while ( isspace(c = getc(file)) );
  127.  
  128.     if ( c == EOF )
  129.         return(NOTHING);
  130.  
  131.     /* if the character is escaped, then ignore it */
  132.     if ( c == '\\' ) {
  133.         getc(file);
  134.         return(OTHER);
  135.     }
  136.  
  137.     /* if the character is '/' and is followed by a '*', then you have
  138.        a comment which you can throw out until the end of comment
  139.        characters come along, example here ->*/
  140.  
  141.     if ( c == '/' ) {
  142.         if ( (c = getc(file)) == '*' ) {
  143.             /* get a comment */
  144.             while ( (c = getc(file)) != EOF && cont ) {
  145.                 if ( c == '/' && eoc ) {
  146.                     cont = 0;
  147.                 } else {
  148.                     eoc = 0;
  149.                 }
  150.                 if ( c == '*' )
  151.                     eoc = 1;
  152.             }
  153.             if ( c == EOF )
  154.                 return(NOTHING);
  155.         }
  156.         ungetc(c,file);
  157.         return(OTHER);
  158.     }
  159.  
  160.  
  161.     if ( iscsymf(c)  ) {
  162.  
  163.         tempc = 0;
  164.         tempfunc[tempc++] = c;
  165.  
  166.         /* to allow tokens like asdf.library, we must check for '.' too */
  167.         while ( iscsym(c = getc(file)) || c == '.' )
  168.             tempfunc[tempc++] = c;
  169.  
  170.         tempfunc[tempc] = '\0';
  171.         ungetc(c,file);
  172.  
  173.         if ( !strcmp("LONG",tempfunc) || !strcmp("ULONG",tempfunc) )
  174.             return(LONGT);
  175.  
  176.         if ( !strcmp("extern",tempfunc) )
  177.             return(EXT);
  178.  
  179.         if ( !strcmp("char",tempfunc) )
  180.             return(CHAR);
  181.  
  182.         if ( !strcmp("myname",tempfunc) )
  183.             return(MYNAME);
  184.  
  185.         if ( !strcmp("myid",tempfunc) )
  186.             return(MYID);
  187.  
  188.         return(IDENT);
  189.     }
  190.  
  191.     switch (c) {
  192.         case ',':
  193.             return(COMMA);
  194.         case ';':
  195.             return(SEMI);
  196.         case '{':
  197.             return(OBRACE);
  198.         case '}':
  199.             return(CBRACE);
  200.         case '(':
  201.             return(OBRACK);
  202.         case ')':
  203.             return(CBRACK);
  204.         case '*':
  205.             return(STAR);
  206.         case '\"':
  207.             return(QUOTE);
  208.         default:
  209.             return(OTHER);
  210.     }
  211. }
  212.  
  213. void addfunc(name,count)
  214. char *name;
  215. int count;
  216. {
  217.     if ( ftcounter < MAXFUNC ) {
  218.         strcpy(functable[ftcounter].name,name);
  219.         functable[ftcounter++].numofargs = count;
  220.     } else {
  221.         error("Out of function name table space. Recompile with bigger MAXFUNC");
  222.     }
  223. }
  224.  
  225. /* process reads the input files and generates the proper output in the
  226.    interface, link and makefiles */
  227. void process(file)
  228. char *file;
  229. {
  230.     FILE *in;               /* pointer to input file */
  231.     int leftcount = 0;      /* counter for number of { } to tell when a
  232.                                function starts */
  233.     int token, argcount;
  234.     char tempname[MAXLEN], str[MAXLEN];
  235.  
  236.     if ( (in = fopen(file,"r")) == NULL ) {
  237.         fprintf(stderr,"Could not open input file %s\n",file);
  238.         return();
  239.     }
  240.  
  241.     /* fill the function name table with the names of the functions in
  242.        the given file */
  243.     while ( (token = getoken(in)) != NOTHING ) {
  244.  
  245.         switch ( token ) {
  246.             /* extern definition... throw out everything to end of statement
  247.                which is denoted by a ; */
  248.             case EXT:
  249.                 while ( (token = getoken(in)) != SEMI && token != NOTHING ) ;
  250.                 break;
  251.  
  252.             /* (maybe) a definition of a function */
  253.             case LONGT:
  254.                 if ( !leftcount ) {
  255.                     if ( (token = getoken(in)) == IDENT ) {
  256.                         if ( (token = getoken(in)) == OBRACK ) {
  257.  
  258.                             argcount = 0;
  259.  
  260.                             /* save the function name from further
  261.                                thrashing by the scanner */
  262.  
  263.                             strcpy(tempname,tempfunc);
  264.  
  265.                             token = getoken(in);
  266.  
  267.                             while ( token != CBRACK ) {
  268.  
  269.                                 if ( token == IDENT ) {
  270.                                     ++argcount;
  271.                                 } else if ( token != COMMA ) {
  272.                                     sprintf(str,"Bad declaration syntax in\
  273.  file %s, function %s\n",file,tempname);
  274.                                     error(str);
  275.                                 }
  276.                                 token = getoken(in);
  277.                             }
  278.  
  279.                             /* if a semicolon follows then this is only a
  280.                                forward declaration and should not be added
  281.                                to the functions list. If anything else,
  282.                                then this is a definition. */
  283.                             if ( (token = getoken(in)) != SEMI ) {
  284.                                 addfunc(tempname,argcount);
  285.                             }
  286.  
  287.                         }
  288.                     }
  289.                 }
  290.                 break;
  291.  
  292.             /* entering a block */
  293.             case OBRACE:
  294.                 ++leftcount;
  295.                 break;
  296.  
  297.             /* exiting a block */
  298.             case CBRACE:
  299.                 if ( leftcount )
  300.                     --leftcount;
  301.                 break;
  302.  
  303.             case CHAR:
  304.                 /* possibly myname is defined */
  305.                 if ( !leftcount ) {
  306.  
  307.                     /* might be declared as char *myname = "foo.library" */
  308.                     if ( (token = getoken(in)) == STAR ) {
  309.  
  310.                         if ( (token = getoken(in)) == MYNAME &&
  311.                             !mynamedef ) {
  312.  
  313.                             token = getoken(in);   /* skip the = */
  314.  
  315.                             if ( (token = getoken(in)) == QUOTE) {
  316.                                 /* we have ignition! */
  317.  
  318.                                 if ( (token = getoken(in)) == IDENT ) {
  319.                                     /* we have liftoff! */
  320.  
  321.                                     strcpy(myname,tempfunc);
  322.                                     mynamedef = 1;
  323.  
  324.                                 }
  325.                             }
  326.                         } else if ( token == MYID && !myiddef ) {
  327.  
  328.                             token = getoken(in);   /* skip the = */
  329.  
  330.                             if ( (token = getoken(in)) == QUOTE) {
  331.                                 /* we have ignition! */
  332.  
  333.                                 if ( (token = getoken(in)) == IDENT ) {
  334.                                     /* we have liftoff! */
  335.  
  336.                                     strcpy(myid,tempfunc);
  337.                                     myiddef = 1;
  338.  
  339.                                 }
  340.                             }
  341.                         }
  342.  
  343.                     /* else declared as char myname[] = "foo.library" */
  344.                     } else if ( token == MYNAME && !mynamedef ) {
  345.  
  346.                         /* now skip the [, ] and = */
  347.                         token = getoken(in);
  348.                         token = getoken(in);
  349.                         token = getoken(in);
  350.  
  351.                         if ( (token = getoken(in)) == QUOTE) {
  352.                             /* we have ignition! */
  353.  
  354.                             if ( (token = getoken(in)) == IDENT ) {
  355.                                 /* we have liftoff! */
  356.  
  357.                                 strcpy(myname,tempfunc);
  358.                                 mynamedef = 1;
  359.  
  360.                             }
  361.                         }
  362.                     } else if ( token == MYID && !myiddef ) {
  363.  
  364.                         /* now skip the [, ] and = */
  365.                         token = getoken(in);
  366.                         token = getoken(in);
  367.                         token = getoken(in);
  368.  
  369.                         if ( (token = getoken(in)) == QUOTE) {
  370.                             /* we have ignition! */
  371.  
  372.                             if ( (token = getoken(in)) == IDENT ) {
  373.                                 /* we have liftoff! */
  374.  
  375.                                 strcpy(myid,tempfunc);
  376.                                 myiddef = 1;
  377.  
  378.                             }
  379.                         }
  380.                     }
  381.                 }
  382.                 break;
  383.  
  384.             default:
  385.                 break;
  386.         }
  387.     }
  388.  
  389.     fclose(in);
  390. }
  391.  
  392. /* converts a file name from a .c to a .o file */
  393. void to_dot_o(out,in)
  394. char *out,*in;
  395. {
  396.     int index = strrpos(in,'.');
  397.  
  398.     strcpy(out,in);
  399.  
  400.     /* if there is no '.' in the file name or if the letter after the '.'
  401.        is not 'c', then concatenate a ".o" to the end of the file name,
  402.        or else just change the 'c' to an 'o' */
  403.  
  404.     if ( index == -1 || in[index+1] != 'c' ) {
  405.         strcat(out,".o");
  406.     } else {
  407.         out[index+1] = 'o';
  408.     }
  409.  
  410.     return();
  411. }
  412.  
  413. /* shutdown cleans up and closes the output files */
  414. void shutdown(argc,argv)
  415. int argc;
  416. char **argv;
  417. {
  418.     int index, num;
  419.     char temp[MAXLEN];
  420.  
  421.     if ( !mynamedef ) {
  422.         strcpy(myname,"mylib.library");
  423.         printf("Myname variable not defined: using \"mylib.library\"\n");
  424.         fprintf(lib,"char myname[] = \"mylib.library\";\n");
  425.     }
  426.  
  427.     if ( !myiddef ) {
  428.         printf("Myid variable not defined: using \"mylib version 1.0\"\n");
  429.         fprintf(lib,"char myid[] = \"mylib version 1.0\";\n");
  430.     }
  431.  
  432.     fprintf(lib,"\n");
  433.     writeto(lib,mandatory);
  434.  
  435.     fprintf(linkh,"APTR libbase;\n\n");
  436.  
  437.     puts("The following LONG functions were found in your source:");
  438.     puts("#  : args name");
  439.     for ( index = 0 ; index < ftcounter ; index++  ) {
  440.         printf("%-3d: %d    %-30s\n",index,functable[index].numofargs,
  441.                functable[index].name);
  442.         fprintf(interface,"        dc.l    X%s\n",functable[index].name);
  443.         fprintf(link,"        LIBDEF _LVO%s\n",functable[index].name);
  444.         fprintf(linkh,"extern LONG %s();\n",functable[index].name);
  445.     }
  446.  
  447.     writeto(link,link2);
  448.  
  449.     writeto(interface,face2);
  450.  
  451.     for ( index = 0 ; index < ftcounter ; index++  ) {
  452.         fprintf(link,"        public _%s\n",functable[index].name);
  453.         fprintf(interface,"        public  _%s\n",functable[index].name);
  454.     }
  455.  
  456.     writeto(interface,facemid);
  457.     fprintf(link,"\n");
  458.  
  459.     for ( index = 0 ; index < ftcounter ; index++  ) {
  460.         fprintf(link,"_%s:\n",functable[index].name);
  461.  
  462.         /* check here for arguments and which registers to put them in */
  463.         if ( functable[index].numofargs > 4 )
  464.             fprintf(link,"        store\n");
  465.  
  466.         for ( num = 0 ; num < functable[index].numofargs ; num++ )
  467.             fprintf(link,"        move.l  %d(sp),%s\n",num*4+4,regs[num]);
  468.  
  469.         fprintf(link,"        move.l  _libbase,a6\n");
  470.  
  471.         if ( functable[index].numofargs > 4 ) {
  472.             fprintf(link,"        jsr     _LVO%s(a6)\n",functable[index].name);
  473.             fprintf(link,"        retrieve\n");
  474.             fprintf(link,"        rts\n\n");
  475.         } else {
  476.             fprintf(link,"        jmp     _LVO%s(a6)\n\n",functable[index].name);
  477.         }
  478.  
  479.         fprintf(interface,"X%s:\n",functable[index].name);
  480.         fprintf(interface,"        setup\n");
  481.  
  482.         /* check here for arguments and how to put them on the stack */
  483.         for ( num = functable[index].numofargs - 1 ; num >= 0 ; num-- )
  484.             fprintf(interface,"        push %s\n",regs[num]);
  485.  
  486.         fprintf(interface,"        jsr _%s\n",functable[index].name);
  487.         fprintf(interface,"        restore ");
  488.         if ( functable[index].numofargs )
  489.             fprintf(interface,"%d",functable[index].numofargs*4);
  490.         fprintf(interface,"\n\n");
  491.     }
  492.  
  493.     fprintf(interface,"        end\n");
  494.  
  495.     fprintf(makefile,"OBJS=startup.o rtag.o interface.o lib.o ");
  496.     for ( index = 1 ; index < argc ; index++ ) {
  497.         to_dot_o(temp,argv[index]);
  498.         fprintf(makefile,"%s ",temp);
  499.     }
  500.  
  501.     fprintf(makefile,"\n\n%s: $(OBJS)\n",myname);
  502.  
  503.     writeto(makefile,makefooter);
  504.  
  505.     /* clean up the open files */
  506.     fclose(linkh);
  507.     fclose(lib);
  508.     fclose(interface);
  509.     fclose(link);
  510.     fclose(makefile);
  511.  
  512.     return();
  513. }
  514.  
  515. main(argc,argv)
  516. int argc;
  517. char **argv;
  518. {
  519.     int index = 1;
  520.  
  521.     /* check for correct usage */
  522.     if ( argc < 2  ) {
  523.         printf("Usage: %s library_source_file ...\n",argv[0]);
  524.         exit(1);
  525.     }
  526.  
  527.     /* open files and write out initial info */
  528.     init();
  529.  
  530.     /* search through each source file for routines and add each routine
  531.        to the appropriate spot */
  532.     while ( index < argc  )
  533.         process(argv[index++]);
  534.  
  535.     /* write out final info and close files */
  536.     shutdown(argc,argv);
  537.  
  538.     exit(0);
  539. }
  540.  
  541.